package com.rdgk.newtech.service.impl;

import com.rdgk.newtech.dao.*;
import com.rdgk.newtech.service.NewTechAnalyseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

@Service
public class NewTechAnalyseServiceImpl implements NewTechAnalyseService {
    @Autowired
    private TechniqueArticleDao techArticleDao;
    @Autowired
    private PaperDao paperDao;
    @Autowired
    private PatentDao patentDao;
    @Autowired
    private CraOrganizationDao organizationDao;
    @Autowired
    private TechniqueWordDao techniqueWordDao;
    @Autowired
    private CraAuthorDao authorDao;

    @Override
    public List<Map<String,Object>> latestTechnologyTrends(Integer topicId, String[] words) {
        Map<String,Object> params = new HashMap<String,Object>();
        params.put("topicId",topicId);
        return techArticleDao.listArticle(params);
    }

    @Override
    public Map<String, Object> technologyDevelopmentTrends(Integer topicId, String[] words, Date startDate, Date endDate) {
        Map<String,Object> params = new HashMap<String,Object>();
        Map<String,Object> results = new HashMap<String,Object>();
        params.put("topicId",topicId);
        params.put("startDate",startDate);
        params.put("endDate",endDate);
        List<Map<String,Object>> alldata = new ArrayList<Map<String,Object>>();
        List<Map<String,Object>> techNumList = techArticleDao.StatisticsNumByYear(params);
        List<Map<String,Object>> paperNumList = paperDao.StatisticsNumByYear(params);
        List<Map<String,Object>> patentNumList = patentDao.StatisticsNumByYear(params);
        alldata.addAll(techNumList);
        alldata.addAll(paperNumList);
        alldata.addAll(patentNumList);
        if(alldata.size()<=0)
            return  results;
        List<Integer> years = new ArrayList<Integer>();
        for (Map<String,Object> data:alldata
             ) {
            if(!years.contains(data.get("publishyear"))){
                years.add((Integer) data.get("publishyear"));
            }
        }

        Collections.sort(years);

        int[] articleNum = new int[years.size()];
        int[] paperNum = new int[years.size()];
        int[] patentNum = new int[years.size()];

        for (Map<String,Object> data:techNumList
                ) {
            articleNum[years.indexOf(data.get("publishyear"))] = data.get("num")==null?0:((Long)data.get("num")).intValue();//将统计数字放到对应的年份中去
        }
        for (Map<String,Object> data:paperNumList
                ) {
            paperNum[years.indexOf(data.get("publishyear"))] = data.get("num")==null?0:((Long)data.get("num")).intValue();//将统计数字放到对应的年份中去
        }
        for (Map<String,Object> data:patentNumList
                ) {
            patentNum[years.indexOf(data.get("publishyear"))] = data.get("num")==null?0:((Long)data.get("num")).intValue();//将统计数字放到对应的年份中去
        }

        results.put("years",years);
        results.put("articleNum",articleNum);
        results.put("paperNum",paperNum);
        results.put("patentNum",patentNum);
        return results;
    }

    @Override
    public List<Map<String,Object>> technologyDevelopmentCours(Integer topicId, String[] words) {
        List<Map<String,Object>> results = new ArrayList<Map<String,Object>>();
        Map<String,Object> params = new HashMap<String,Object>();
        params.put("topicId",topicId);
        results.addAll(techArticleDao.listByYear(params));
        results.addAll(paperDao.listByYear(params));
        results.addAll(patentDao.listByYear(params));
        return results;
    }

    @Override
    public Map<String, Object> technologyHotspot(Integer topicId, String[] words) {//待测试，一个月以内的算热词（未设置）
        //先通过主题找到相关关键词，然后根据关键词与网络新闻动态的关系表找到网络新闻动态
        Map<String,Object> params = new HashMap<String,Object>();
        params.put("topicId",topicId);
        Map<String,Object> results = new HashMap<String,Object>();
        params.put("topicId",topicId);
        results.put("articleNum",techArticleDao.StatisticsNumByHotword(params));
        results.put("paperNum",paperDao.StatisticsNumByHotword(params));
        results.put("patentNum",patentDao.StatisticsNumByHotword(params));
        return results;
    }

    @Override
    public List<Map<String,Object>> technologyRegionalDistribution(Integer topicId, String[] words) {
        Map<String,Object> params = new HashMap<String,Object>();
        params.put("topicId",topicId);
        return organizationDao.statisticsNumByAddressForMap(params);
    }

    @Override
    public List<Map<String,Object>> technologySourceDistribution(Integer topicId, String[] words) {//待测试，专利表没有source字段
        List<Map<String,Object>> results = new ArrayList<Map<String,Object>>();
        Map<String,Object> params = new HashMap<String,Object>();
        params.put("topicId",topicId);
        results.addAll(techArticleDao.StatisticsNumBySource(params));
        results.addAll(paperDao.StatisticsNumBySource(params));
        results.addAll(patentDao.StatisticsNumBySource(params));
        return results;
    }

    @Override
    public Map<String, Object> hotWordsAtlas(Integer topicId, String keyword) {
        Map<String,Object> params = new HashMap<String,Object>();
        params.put("topicId",topicId);
        params.put("keyword",keyword);
        Map<String,Object> results = new HashMap<String,Object>();
        List<Map<String,Object>> nodes = new ArrayList<Map<String,Object>>();//节点列表
        List<Map<String,Object>> edges = new ArrayList<Map<String,Object>>();//关系列表

        List<Map<String,Object>> hotWordNodes = new ArrayList<Map<String,Object>>();//热词节点
        List<Map<String,Object>> techniqueArticleNodes = new ArrayList<Map<String,Object>>();//网络新闻动态节点
        List<Map<String,Object>> paperNodes = new ArrayList<Map<String,Object>>();//论文节点
        List<Map<String,Object>> patentNodes = new ArrayList<Map<String,Object>>();//专利节点
        List<Map<String,Object>> authorNodes = new ArrayList<Map<String,Object>>();//专家节点
        List<Map<String,Object>> organizationNodes = new ArrayList<Map<String,Object>>();//机构节点

        List<Map<String,Object>> hotwordArticleEdges = new ArrayList<Map<String,Object>>();//热词与网络新闻动态关系
        List<Map<String,Object>> hotwordPaperEdges = new ArrayList<Map<String,Object>>();//热词与论文节点
        List<Map<String,Object>> hotwordPatentEdges = new ArrayList<Map<String,Object>>();//热词与专利节点
        List<Map<String,Object>> orgTechEdges = new ArrayList<Map<String,Object>>();//机构与网络新闻动态关系
        List<Map<String,Object>> authorTechEdges = new ArrayList<Map<String,Object>>();//专家与网络新闻动态关系
        List<Map<String,Object>> authorPaperEdges = new ArrayList<Map<String,Object>>();//专家与论文关系
        List<Map<String,Object>> authorPatentEdges = new ArrayList<Map<String,Object>>();//专家与专利关系
        List<Map<String,Object>> authorOrgEdges = new ArrayList<Map<String,Object>>();//专家与机构关系

        hotWordNodes = techniqueWordDao.getHotwords(params);//获取领域属于热词的关键词
        List<Map<String,Object>> hotwordArticle = techArticleDao.getArticleByHotword(params);
        List<Object> articleIdParams = new ArrayList<Object>();//用于传递参数的网络新闻动态id的集合
        for (Map<String,Object> article:hotwordArticle
             ) {
            if(!articleIdParams.contains(article.get("articleid"))){
                Map<String,Object> techniqueArticle = new HashMap<String,Object>();//创建网络动态节点
                techniqueArticle.put("id","tech_"+article.get("articleid"));
                techniqueArticle.put("label",article.get("title"));
                techniqueArticleNodes.add(techniqueArticle);
                articleIdParams.add(article.get("articleid"));//保存每个网络新闻动态的id
            }
            Map<String,Object> hotwordArticleEdge = new HashMap<String,Object>();//创建热词网络动态关系
            hotwordArticleEdge.put("sourceID",article.get("wordid"));
            hotwordArticleEdge.put("targetID","tech_"+article.get("articleid"));
            hotwordArticleEdges.add(hotwordArticleEdge);
        }

        List<Map<String,Object>> hotwordPaper = paperDao.getPaperByHotword(params);
        List<Object> paperIdParams = new ArrayList<Object>();//用于传递参数的论文id的集合
        for (Map<String,Object> paper:hotwordPaper
                ) {
            if(!paperIdParams.contains(paper.get("paperid"))){
                Map<String,Object> papernode = new HashMap<String,Object>();//创建论文节点
                papernode.put("id","paper_"+paper.get("paperid"));
                papernode.put("label",paper.get("title"));
                paperNodes.add(papernode);
                paperIdParams.add(paper.get("paperid"));
            }
            Map<String,Object> hotwordPaperEdge = new HashMap<String,Object>();//创建热词论文关系
            hotwordPaperEdge.put("sourceID",paper.get("wordid"));
            hotwordPaperEdge.put("targetID","paper_"+paper.get("paperid"));
            hotwordPaperEdges.add(hotwordPaperEdge);
        }

        List<Map<String,Object>> hotwordPatent = patentDao.getPatentByHotword(params);
        List<Object> patentIdParams = new ArrayList<Object>();//用于传递参数的论文id的集合
        for (Map<String,Object> patent:hotwordPatent
                ) {
            if(!patentIdParams.contains(patent.get("patentid"))){
                Map<String,Object> patendnode = new HashMap<String,Object>();//创建专利节点
                patendnode.put("id","patent_"+patent.get("patentid"));
                patendnode.put("label",patent.get("title"));
                patentNodes.add(patendnode);
                patentIdParams.add(patent.get("patentid"));
            }
            Map<String,Object> hotwordPatenddge = new HashMap<String,Object>();//创建专利与热词关系
            hotwordPatenddge.put("sourceID",patent.get("wordid"));
            hotwordPatenddge.put("targetID","patent_"+patent.get("patentid"));
            hotwordPatentEdges.add(hotwordPatenddge);
        }

        params.put("relArticleList",articleIdParams);
        params.put("relPaperList",paperIdParams);
        params.put("relPatentList",patentIdParams);
        List<Map<String,Object>> relAuthors = authorDao.getAuthorByHotword(params);
        List<Object> tmpAuthorIds = new ArrayList<Object>();//临时存放专家id的list，用于去重
        for (Map<String,Object> relAuthor:relAuthors
             ) {
            Object authorid = relAuthor.get("authorid");
            if(!tmpAuthorIds.contains(authorid)){//判断专家id是否已经出现过
                Map<String,Object> authorNode = new HashMap<String,Object>();//创建专家节点
                authorNode.put("id","author_"+relAuthor.get("authorid"));
                authorNode.put("label",relAuthor.get("name"));
                authorNodes.add(authorNode);
                tmpAuthorIds.add(authorid);//标记该专家已经出现过
            }
            if("0".equals(relAuthor.get("reltype"))){//创建专家与网络动态关系
                Map<String,Object> authorArticleEdge = new HashMap<String,Object>();
                authorArticleEdge.put("sourceID","author_"+relAuthor.get("authorid"));
                authorArticleEdge.put("targetID","tech_"+relAuthor.get("targetID"));
                authorTechEdges.add(authorArticleEdge);
            }
            if("1".equals(relAuthor.get("reltype"))){//创建专家与论文关系
                Map<String,Object> authorPaperEdge = new HashMap<String,Object>();
                authorPaperEdge.put("sourceID","author_"+relAuthor.get("authorid"));
                authorPaperEdge.put("targetID","paper_"+relAuthor.get("targetID"));
                authorPaperEdges.add(authorPaperEdge);
            }
            if("2".equals(relAuthor.get("reltype"))) {//创建专家与专利关系{
                Map<String, Object> authorPatentEdge = new HashMap<String, Object>();
                authorPatentEdge.put("sourceID","author_"+relAuthor.get("authorid"));
                authorPatentEdge.put("targetID","patent_"+relAuthor.get("targetID"));
                authorPatentEdges.add(authorPatentEdge);
            }
        }

        List<Map<String,Object>> relOrgs = organizationDao.getOrgByArticle(params);
        List<Object> tmpOrgIds = new ArrayList<Object>();//临时存放机构id的list，用于去重
        for (Map<String,Object> relorg:relOrgs
             ) {
            Object orgid = relorg.get("orgid");
            if(!tmpOrgIds.contains(orgid)){
                Map<String,Object> orgNode = new HashMap<String,Object>();//创建机构节点
                orgNode.put("id","org_"+relorg.get("orgid"));
                orgNode.put("label",relorg.get("name"));
                organizationNodes.add(orgNode);
                tmpOrgIds.add(orgid);//标记该机构已经出现过
            }
            Map<String,Object> orgArticleEdge = new HashMap<String,Object>();
            orgArticleEdge.put("sourceID","org_"+relorg.get("orgid"));
            orgArticleEdge.put("targetID","tech_"+relorg.get("targetID"));
            orgTechEdges.add(orgArticleEdge);
        }

        params.put("tmpAuthorIds",tmpAuthorIds);
        params.put("tmpOrgIds",tmpOrgIds);
        List<Map<String,Object>> relAuthorOrgs = organizationDao.getAuthorOrgRelations(params);//创建专家和机构之间的关系
        for (Map<String,Object> relAuthorOrg:relAuthorOrgs
             ) {
            Map<String,Object> authorOrgEdge = new HashMap<String,Object>();
            authorOrgEdge.put("sourceID","author_"+relAuthorOrg.get("sourceID"));
            authorOrgEdge.put("targetID","org_"+relAuthorOrg.get("targetID"));
            authorOrgEdges.add(authorOrgEdge);
        }

        //将所有节点增加到nodes集合中
        nodes.addAll(hotWordNodes);
        nodes.addAll(authorNodes);
        nodes.addAll(organizationNodes);
        nodes.addAll(techniqueArticleNodes);
        nodes.addAll(paperNodes);
        nodes.addAll(patentNodes);
        //将所有关系增加到edges集合中
        edges.addAll(hotwordArticleEdges);
        edges.addAll(hotwordPaperEdges);
        edges.addAll(hotwordPatentEdges);
        edges.addAll(orgTechEdges);
        edges.addAll(authorTechEdges);
        edges.addAll(authorPaperEdges);
        edges.addAll(authorPatentEdges);
        edges.addAll(authorOrgEdges);
        //将关系和节点列表添加到结果集中
        results.put("nodes",nodes);
        results.put("edges",edges);
        return results;
    }

    @Override
    public Map<String, Object> hotWordDevelopmentTrend(Integer topicId, String[] words) {
        Map<String,Object> params = new HashMap<String,Object>();
        Map<String,Object> results = new HashMap<String,Object>();
        List<Map<String,Object>> totaldata = new ArrayList<Map<String,Object>>();
        List<Object> years = new ArrayList<Object>();
        Map<String,Object> hotwordNum = new HashMap<String,Object>();//hotwordNum存放结构:key是每个关键词，value是一个长度years一样的数组。
        params.put("topicId",topicId);
        totaldata = techArticleDao.StatisticsNumByHotwordAndYear(params);
        for (Map<String,Object> data:totaldata//获取年份列表
             ) {
            if(!years.contains(data.get("publishyear"))){
                years.add(data.get("publishyear"));
            }
        }
        for (Map<String,Object> data:totaldata
                ) {
            String hotword = (String)data.get("keyword");
            if(hotwordNum.get(hotword)==null){
                int[] yearnum = new int[years.size()];//数组的长度与年度list长度一样，数组的值与年度一一对应，数组默认值是0
                yearnum[years.indexOf(data.get("publishyear"))] = data.get("sumnum")==null?0:((BigDecimal) data.get("sumnum")).intValue();//将统计数字放到对应的年份中去
                hotwordNum.put(hotword,yearnum);
            }else{
                int[] yearnum = (int[])hotwordNum.get(hotword);
                yearnum[years.indexOf(data.get("publishyear"))] = data.get("sumnum")==null?0:((BigDecimal) data.get("sumnum")).intValue();//将统计数字放到对应的年份中去
            }
        }
        //results.put("articleNum",techArticleDao.StatisticsNumByHotwordAndYear(params));
        //results.put("paperNum",paperDao.StatisticsNumByHotwordAndYear(params));
        //results.put("patentNum",patentDao.StatisticsNumByHotwordAndYear(params));
        results.put("years",years);
        results.put("hotwordNums",hotwordNum);
        return results;
    }

    @Override
    public Map<String, Object> coWordAnalysis(Integer topicId) {
        Map<String,Object> results = new HashMap<String,Object>();
        List<Map<String,Object>> nodes = new ArrayList<Map<String,Object>>();
        List<Map<String,Object>> edges = new ArrayList<Map<String,Object>>();
        Map<String,Object> params = new HashMap<String,Object>();
        params.put("topicId",topicId);
        List<Map<String,Object>> hotwordRelations = techniqueWordDao.getHotwordsByRelation(params);
        List<Object> tmpHotwordIds = new ArrayList<Object>();//临时存放热词id的list，用于去重
        Map<String,Object> articleIncludeWords = new HashMap<String,Object>();//用于记录每个动态包含的关键词
        Map<String,Integer> relIndex = new HashMap<String,Integer>();//用于记录每个关系在Edges中的下标
        for (Map<String,Object> wordRelation:hotwordRelations
             ) {
            Object wordid = wordRelation.get("wordid");
            Object articleid = wordRelation.get("articleid");
            if(!tmpHotwordIds.contains(wordid)){
                Map<String,Object> wordNode = new HashMap<String,Object>();//创建机构节点
                wordNode.put("id",wordRelation.get("wordid"));
                wordNode.put("label",wordRelation.get("keyword"));
                nodes.add(wordNode);
                tmpHotwordIds.add(wordid);//标记该热词已经出现过
            }
            List<Object> articleWords = (List<Object>)articleIncludeWords.get(articleid.toString());
            if (articleWords==null){//如果该动态中没有关键词则增加该条记录的热词
                articleWords = new ArrayList<Object>();
                articleWords.add(wordid);
                articleIncludeWords.put(articleid.toString(),articleWords);
            }else{//如果该动态中存在关键词，则根据该条记录的关键词创建关系节点
                for (Object articleWord:articleWords
                     ) {
                    if(wordid.equals(articleWord))//如果关键词一样则跳过
                        continue;
                    Map<String,Object> wordRelEdge = new HashMap<String,Object>();
                    String indexKey = wordid+"REL"+articleWord;//自定义的键，用于存放每个关系在edges中的下标
                    if(relIndex.get(indexKey)==null){//如果不存关系则创建关系
                        wordRelEdge.put("sourceID",wordid);
                        wordRelEdge.put("targetID",articleWord);
                        wordRelEdge.put("size",1);
                        relIndex.put(indexKey,edges.size());//存入该关系的下标
                        edges.add(wordRelEdge);
                    }else{//如果处在关系则更新关系的size
                        wordRelEdge = edges.get(relIndex.get(indexKey));
                        Integer size = (Integer) wordRelEdge.get("size");
                        size+=1;
                        wordRelEdge.put("size",size);//size加1，代表两个热词共同出现的次数加1
                    }
                }
                articleWords.add(wordid);
            }
        }
        results.put("nodes",nodes);
        results.put("edges",edges);
        return results;
    }
}
